#include <new>
#include "rdx.h"
#include "rdx_objectmanagement.hpp"
#include "rdx_interpret.hpp"
#include "rdx_plugin.hpp"
#include "rdx_ilcomp.hpp"
#include "rdx_runtime.hpp"

RDX_DYNLIB_API void RDX_Initialize()
{
	RDX::Initialize();
}


RDX_DYNLIB_API ::RDX::ObjectManagement::IObjectManager *RDX_CreateObjectManager(const ::RDX::ObjectManagement::Allocator *alloc, const ::RDX::ObjectManagement::INativeTypeHost *nth, const ::RDX::Programmability::ICodeProvider *cp)
{
	return RDX::ObjectManagement::CreateObjectManager(*alloc, nth, cp);
}

RDX_DYNLIB_API ::RDX::Programmability::ICodeProvider *RDX_CreateInterpreterCodeProvider(const ::RDX::ObjectManagement::Allocator *alloc, const ::RDX::Programmability::PrecompiledCodeModule **modules, ::RDX::LargeInt numModules)
{
	RDX::Interpreter::InterpreterCodeProvider *cp = alloc->CAlloc<RDX::Interpreter::InterpreterCodeProvider>(1);
	if(!cp)
		return NULL;
	new (cp) RDX::Interpreter::InterpreterCodeProvider(*alloc, modules, numModules);
	return cp;
}

RDX_DYNLIB_API const RDX::ObjectManagement::INativeTypeHost *RDX_GetNumericTypesPlugin()
{
	return RDX::Plugins::GetNumericTypesPlugin();
}

RDX_DYNLIB_API int RDX_RuntimeTrace_TraceParent(const ::RDX::Programmability::RuntimeTrace *trace, ::RDX::Programmability::RuntimeTrace *outTrace)
{
	return trace->TraceParent(*outTrace) ? 1 : 0;
}

RDX_DYNLIB_API ::RDX::LargeInt RDX_RuntimeTrace_NumJournalEntries(const ::RDX::Programmability::RuntimeTrace *trace)
{
	return trace->NumJournalEntries();
}

RDX_DYNLIB_API void RDX_RuntimeTrace_JournalEntry(const ::RDX::Programmability::RuntimeTrace *trace, ::RDX::LargeInt index, ::RDX::Programmability::Journal *outJournal)
{
	*outJournal = trace->JournalEntry(index);
}

RDX_DYNLIB_API void RDX_RuntimeTrace_ScanJournals(const ::RDX::Programmability::RuntimeTrace *trace, ::RDX::Programmability::JournalScanState *outJournalScanState)
{
	*outJournalScanState = trace->ScanJournals();
}

RDX_DYNLIB_API void RDX_RuntimeTrace_GetFileNameAndLineNumber(const ::RDX::Programmability::RuntimeTrace *trace, const ::RDX::Programmability::String **outFilename, ::RDX::LargeInt *outLineNumber)
{
	trace->GetFileNameAndLineNumber(*outFilename, *outLineNumber);
}

RDX_DYNLIB_API void RDX_JournalScanState_NextJournal(::RDX::Programmability::JournalScanState *jss, ::RDX::Programmability::Journal *outJournal)
{
	*outJournal = jss->NextJournal();
}

RDX_DYNLIB_API void RDX_ExportSource(::RDX::ObjectManagement::IObjectManager *objm, void *stdFile, int domain)
{
	::RDX::SourceExport::ExportSource(objm, stdFile, static_cast<::RDX::ObjectManagement::Domain>(domain));
}

RDX_DYNLIB_API void *RDX_RuntimeUtilities_ArrayIndex(void *o, const ::RDX::Programmability::RuntimeStackValue *rsv)
{
	return ::RDX::Programmability::RuntimeUtilities::ArrayIndex(o, rsv);
}

RDX_DYNLIB_API void *RDX_RuntimeUtilities_NewObjectInstance(::RDX::OperationContext *ctx, ::RDX::ObjectManagement::IObjectManager *objm,
	const ::RDX::Programmability::Type *t, const ::RDX::Programmability::RuntimeStackValue *dimensions, ::RDX::LargeInt numDimensions)
{
	return ::RDX::Programmability::RuntimeUtilities::NewObjectInstance(ctx, objm, t, dimensions, numDimensions);
}

RDX_DYNLIB_API int RDX_RuntimeUtilities_ExpandFrame(void *stackBase, void *frameBase, ::RDX::LargeInt stackSize, ::RDX::Programmability::RuntimeStackFrame **newBP, int hasInsertionPoint, int hasNativeFrame)
{
	return ::RDX::Programmability::RuntimeUtilities::ExpandFrame(stackBase, frameBase, stackSize, newBP, hasInsertionPoint != 0, hasNativeFrame != 0) ? 1 : 0;
}

RDX_DYNLIB_API int RDX_RuntimeUtilities_EnterMethodInline(::RDX::ObjectManagement::IObjectManager *objm, const ::RDX::Programmability::Method *m, ::RDX::Programmability::RuntimeStackFrame *currentFrame,
	void *frameBase, void *stackBase, ::RDX::Programmability::RuntimeStackValue *prv, ::RDX::Programmability::RuntimeStackFrame *newFrame)
{
	return ::RDX::Programmability::RuntimeUtilities::EnterMethodInline(objm, m, currentFrame, frameBase, stackBase, prv, newFrame) ? 1 : 0;
}

RDX_DYNLIB_API int RDX_RuntimeUtilities_EnterMethodRoot(::RDX::ObjectManagement::IObjectManager *objm, const ::RDX::Programmability::Method *m, ::RDX::Programmability::RuntimeStackFrame *currentFrame, void *frameBase, void *stackBase,
	::RDX::Programmability::RuntimeStackValue *prv, ::RDX::Programmability::RuntimeStackFrame *newFrame, void *recordedInsertionPoint, int throughNative, const ::RDX::Programmability::Method *viaMethod, const ::RDX::Programmability::RuntimeStackFrame *subFrame)
{
	return ::RDX::Programmability::RuntimeUtilities::EnterMethodRoot(objm, m, currentFrame, frameBase, stackBase, prv, newFrame, recordedInsertionPoint, throughNative != 0, viaMethod, subFrame);
}
